--10. Consider three two-dimensional points, a, b, and c. If we look at the angle formed
--by the line segment from a to b and the line segment from b to c, it turns left, turns
--right, or forms a straight line. Define a Direction data type that lets you represent
--these possibilities.

data Direction = TurnLeft
               | TurnRight
               | GoStraight
                 deriving (Eq, Show)


--11. Write a function that calculates the turn made by three two-dimensional points
--and returns a Direction

data Point = Point {
               pointX :: Double
             , pointY :: Double
             } deriving (Eq, Show)

data Vector = Vector {
                vectorX :: Double
              , vectorY :: Double
              } deriving (Eq, Show)

makeVectorFromTwoPoints (Point x1 y1) (Point x2 y2) = Vector (x2-x1) (y2-y1)

-- cos=a*b/[|a|*|b|] = (x1x2+y1y2)/[√[x1^2+y1^2]*√[x2^2+y2^2]]
-- 这种办法算的是两个向量之间夹的锐角 
-- 计算两个向量之间的夹角
--vecAngle (Vector x1 y1) (Vector x2 y2) = acos ((x1*x2+y1*y2) / (sqrt (x1*x1+y1*y1) * sqrt (x2*x2+y2*y2)))


-- a = atan2d(x1*y2-y1*x2,x1*x2+y1*y2); 
-- https://ww2.mathworks.cn/matlabcentral/answers/180131-how-can-i-find-the-angle-between-two-vectors-including-directional-information
-- 
-- 这个atan2啥意思，我模模糊糊，原理更不清楚；反正它跟atan不一样
-- 测试数据
--let v1 = makeVectorFromTwoPoints (Point 0 0) (Point 1 0)
--let v2 = makeVectorFromTwoPoints (Point 1 0) (Point 1 1)
--let v3 = makeVectorFromTwoPoints (Point 1 0) (Point 2 0)
-- *Main> vecAngle v1 v2
-- 1.5707963267948966
-- *Main> vecAngle v2 v1
-- -1.5707963267948966
-- *Main> vecAngle v1 v3
-- 0.0
vecAngle (Vector x1 y1) (Vector x2 y2) = atan2 (x1*y2-y1*x2) (x1*x2+y1*y2)

-- 计算往哪个方向              
calcTurn a b c = 
  let v1 = makeVectorFromTwoPoints a b
      v2 = makeVectorFromTwoPoints b c
      angle = vecAngle v1 v2
  in
    if angle > 0
    then TurnLeft
    else if angle == 0
         then GoStraight
         else TurnRight

-- 测试用例：
-- calcTurn (Point 0 0) (Point 1 0) (Point 1 1)
-- 结果: TurnLeft
-- calcTurn (Point 0 0) (Point 1 0) (Point 1 (-1))
-- 结果: TurnRight
-- calcTurn (Point 0 0) (Point 1 0) (Point 2 0)
-- 结果: GoStraight


--12. Define a function that takes a list of two-dimensional points and computes the
--direction of each successive triple. Given a list of points [a,b,c,d,e], it should
--begin by computing the turn made by [a,b,c], then the turn made by [b,c,d],
--then [c,d,e]. Your function should return a list of Direction.

calcTurnOfList list = if length list < 3
                      then []
                      else
                        let p1 = head list
                            p2 = head (tail list)
                            p3 = head (tail (tail list))
                        in (calcTurn p1 p2 p3) : calcTurnOfList (tail list)

-- 测试用例：
--calcTurnOfList [(Point 0 0), (Point 1 6), (Point 2 4), (Point 3 3), (Point 4 4), (Point 5 1)]
-- 结果: [TurnRight,TurnLeft,TurnLeft,TurnRight]

